<template>
	<div :class="classes">
		<div ref="control" :class="{[prefixCls+'-cascader-control']:true,'focus':show,[prefixCls+'-cascader-show-clear']:clearable}">
			<!-- <div :class="[prefixCls+'-cascader-tags']" v-if="multiple && !filterable"></div> -->
            <div class="input-control" :class="{'placeholder':showPlaceholder}">
                <input type="text" readonly :value="newValue" :placeholder="placeholder" :class="[prefixCls+'-cascader-input-inner']" v-if="!filterable">
                <input type="text" v-model="filter.keyword" :placeholder="filter.placeholder" :class="[prefixCls+'-cascader-input-inner']" @keyup="filterKeyup" v-else>
                <div v-if="filterable" :class="[prefixCls+'-cascader-filter-label']">
                    {{ newValue }}
                </div>
            </div>
            <span :class="[prefixCls+'-cascader-suffix-clear']" v-if="clearable&&newValue.length>0" @click="clearValue" :style="clearable?'cursor:pointer':''"><i class="icon icon-error-circle"></i></span>
            <i class="icon icon-arrow-down"></i>
		</div>
        <transition name="animation-drop">
            <div 
            :class="{
                [prefixCls+'-cascader-drop-down']:true,
                'is-multiple':multiple,
                [prefixCls+'-cascader-drop-down-empty']:dataArr.length==0,
                [prefixCls+'-cascader-not-found']:filter.show && filter.list == '',
            }" 
            v-if="show" 
            ref="drop">
                <div :class="[prefixCls+'-cascader-panel']" v-if="!filter.show">
                    <div class="no-data" v-if="dataArr.length==0">
                        {{emptyText}}
                    </div>
                    <template v-else>
                        <div :class="[prefixCls+'-cascader-menu','min-scrollbar']">
                            <ul :class="[prefixCls+'-cascader-menu-list']">
                                <li v-for="(item,index) in dataArr" :key="item.value" 
                                @click="loadChild(item,1,index,'click')" 
                                @mouseenter="trigger === 'hover'?loadChild(item,1,index,'hover'):false" 
                                @mouseleave="trigger === 'hover'?out(item,1):false"
                                :class="{'active':activeCls(item,1,index),'disabled':item.disabled}">
                                    <span>{{item.label}}</span>
                                    <i class="icon icon-loading" v-if="item.loading"></i>
                                    <template v-else>
                                        <i class="icon icon-arrow-right" v-if="item.children"></i>
                                    </template>
                                </li>
                            </ul>
                        </div>
                        <div :class="[prefixCls+'-cascader-menu','min-scrollbar']" v-if="childData.data1.children">
                            <ul :class="[prefixCls+'-cascader-menu-list']">
                                <li v-for="(item,index) in childData.data1.children" :key="item.value" 
                                @click="loadChild(item,2,index,'click')" 
                                @mouseenter="trigger === 'hover'?loadChild(item,2,index,'hover'):false" 
                                @mouseleave="trigger === 'hover'?out(item,2):false"
                                :class="{'active':activeCls(item,2,index),'disabled':item.disabled}">
                                    <span>{{item.label}}</span>
                                    <i class="icon icon-loading" v-if="item.loading"></i>
                                    <template v-else>
                                        <i class="icon icon-arrow-right" v-if="item.children"></i>
                                    </template>
                                </li>
                            </ul>
                        </div>
                        <div :class="[prefixCls+'-cascader-menu','min-scrollbar']" v-if="childData.data2.children">
                            <ul :class="[prefixCls+'-cascader-menu-list']">
                                <li v-for="(item,index) in childData.data2.children" :key="item.value" 
                                @click="loadChild(item,3,index,'click')" 
                                @mouseenter="trigger === 'hover'?loadChild(item,3,index,'hover'):false" 
                                @mouseleave="trigger === 'hover'?out(item,3):false"
                                :class="{'active':activeCls(item,3,index),'disabled':item.disabled}">
                                    <span>{{item.label}}</span>
                                    <i class="icon icon-loading" v-if="item.loading"></i>
                                    <template v-else>
                                        <i class="icon icon-arrow-right" v-if="item.children"></i>
                                    </template>
                                </li>
                            </ul>
                        </div>
                        <!-- <div :class="[prefixCls+'-cascader-menu','min-scrollbar']" v-if="childData.data3.children">
                            <ul :class="[prefixCls+'-cascader-menu-list']">
                                <li v-for="(item,index) in childData.data3.children" :key="item.value" 
                                @click="loadChild(item,4,index,'click')" 
                                @mouseenter="trigger === 'hover'?loadChild(item,4,index,'hover'):false" 
                                @mouseleave="trigger === 'hover'?out(item,4):false"
                                :class="{'active':activeCls(item,4,index),'disabled':item.disabled}">
                                    <span>{{item.label}}</span>
                                    <i class="icon icon-loading" v-if="item.loading"></i>
                                    <template v-else>
                                        <i class="icon icon-arrow-right" v-if="item.children"></i>
                                    </template>
                                </li>
                            </ul>
                        </div> -->
                    </template>
                </div>
                <div :class="[prefixCls+'-cascader-filter-list']" v-else>
                    <div v-if="filter.list == ''" class="nodata">
                        {{ emptyText }}
                    </div>
                    <ul v-else :class="[prefixCls+'-cascader-filter-list-item','min-scrollbar']" v-html="filter.list">
                    </ul>
                    <!-- 搜索的结果 -->
                </div>
            </div>
        </transition>
	</div>
</template>

<script>
import { prefixCls } from '../prefix'
import './cascader.css'
import axios from 'axios';
import popup from '../../utils/popup'

export default {
    name: `${prefixCls}Cascader`,
    props:{
        value: {//通过v-model传进来
            type:[String , Array],
            default: () => []
        },
        placeholder: {//默认显示的文本
            type:String,
            default:'请选择'
        },
		filterPlaceholder: String,//仅对搜索有效，搜索输入框placeholder提示语
        data:Array,
        multiple:{//多选
            type:Boolean,
            default:false
        },
        filterable: {//显示搜索输入框
            type: Boolean,
            default: false
        },
        transfer:{//弹层放置于body内
            type:Boolean,
            default: false
        },
        disabled: {//是否禁用
            type: Boolean,
            default: false
        },
        trigger: {
            type: String,
            default: 'click',
        },
        clearable: {
            type: Boolean,
            default: false
        },
        emptyText: {
            type: String,
            default: '无匹配数据'
        },
        changeOnSelect: {//点任何一级都可以选择
            type: Boolean,
            default: false
        },
        size: String, //选择框尺寸
        loadData: Function,//动态加载选项
    },
    data () {
        return {
            prefixCls: prefixCls,
            dataArr:this.data,
            show:false,
            showPlaceholder: this.placeholder ? true : false,
            activeVal:this.value,//当前选中项
            isClickTag:false, //是否点击了tag的删除
            childData:{
                data1:'',//二级数据
                data2:'',//三级数据
                // data3:'',//四级数据
            },
            newValue:'',//存储的选择value
            tempValue:'',//选择时候存储当前选择项
            active:{//hover 当前显示class
                current1:'',
                current2:'',
                current3:'',
                // current4:'',
            },
            filter:{
                keyword:'',//搜索关键词
                placeholder:this.placeholder,
                show: false,
                list:'',
            },
            // demo:[]
         }
    },
    watch: {
        data(newval) {
            this.dataArr = newval
            this.initData()
        },
        value(newval) {
            this.activeVal = newval
            this.valueCls
            if(this.filterable && newval.length > 0) {
                this.filter.placeholder = ''
            }else{
                this.filter.placeholder = this.placeholder
            }
        },
        'filter.keyword': {
            handler(n,o) {
                 this.filterKeyWord(n)
            }
        }
    },
    mounted() {
    	document.addEventListener('click', this._showHide);

        //已选项处理成可读value
        this.valueCls

        // 绑定filter中li点击事件
        window.selectItem = this.selectItem

        // let item = []
        // this.dataArr.map( (d)=> {
        //     item.push(d)
        // })
        // this.demo.push(item)
        // console.log('demo:',this.demo)
    },
    methods: {
        initData() {
            // 初始化子级数据，将新的值与旧的值合并覆盖,如有已选的，展开
            Object.assign(this.active, this.$options.data().active)
            Object.assign(this.childData, this.$options.data().childData)
            //赋值下级数据
            for(let i=0;i<this.activeVal.length;i++) {
                this.dataArr.map((d,index)=>{
                    if(d.value == this.activeVal[i]) {
                        this.childData['data'+(i+1)] = d
                        this.active['current'+(i+1)] = index
                        if(d.children) {
                            d.children.map((r,n)=>{
                                if(r.value == this.activeVal[i+1]) {
                                    this.childData['data'+(i+2)] = r
                                    this.active['current'+(i+2)] = n
                                    if(r.children) {
                                        r.children.map((x,y)=>{
                                            if(x.value == this.activeVal[i+2]) {
                                                this.childData['data'+(i+3)] = x
                                                this.active['current'+(i+3)] = y
                        // if(x.children) {
                        //     x.children.map((a,b)=>{
                        //         if(a.value == this.activeVal[i+3]) {
                        //             this.childData['data'+(i+4)] = a
                        //             this.active['current'+(i+4)] = b
                        //             if(a.children) {
                        //                 a.children.map((c,d)=>{
                        //                     if(c.value == this.activeVal[i+3]) {
                        //                         this.active['current'+(i+4)] = d
                        //                     }
                        //                 })
                        //             }
                        //         }
                        //     })
                        // }
                                            }
                                        })
                                    }
                                }
                            })
                        }
                    }
                })
            }
        },
    	_showHide(e){
            // 多选tag点击删除时候不收起下拉层
            if(this.multiple && this.isClickTag) {
                this.isClickTag = false;
                return false;
            }
            if (this.$el.contains(e.target) || (this.$refs.drop && (e.target.nodeName == 'LI' || e.target.nodeName == 'I'))) {
                // console.log(e)
                if(e.target.className.indexOf('control')>0 || e.target.className.indexOf('input-inner')>0 || e.target.parentNode.className.indexOf('control')>0 ) {
                    this.disabled == false ? this.show = !this.show : "";
                    //展开时候初始化已选项，显示已选子级
                    this.$nextTick(()=>{
                        this.initData()
                    })
                    this.$emit('on-open-change',this.show)
                }

                if(this.transfer){
                    if(this.show){
                       this.$nextTick(()=> {
                            popup.create({drop:this.$refs.drop})
                            const DOMRect1 = this.$refs.control.getBoundingClientRect(),
                                _w1 = DOMRect1.width;
                            this.$refs.drop.style.minWidth = _w1+'px';
                       })
                    }
                }
                this.$nextTick(()=> {
                  popup.position({
                    trigger:this.$refs.control,//触发层
                    drop:this.$refs.drop,//下拉层
                    body:this.transfer,//是否将弹层置于body中
                  })
                })

                // 开启搜索
                this.tempValue = this.newValue
                if(this.filterable && this.filter.keyword) {
                    let k = this.filter.keyword
                    this.filterKeyWord(k)

                }
                // console.log('open:',this.active)
            } else {
                this.show = false;
                //收起时候，恢复默认已选项
                this.newValue = this.tempValue
                // this.tempValue = this.newValue
                Object.assign(this.active, this.$options.data().active)
                // Object.assign(this.childData, this.$options.data().childData)
                // 关闭时清空已有搜索字段
                this.filter.keyword = '';
                this.filter.show = false;
                // console.log('close',this.tempValue)
            }
    	},
        loadChild(item,level,index,trigger) {
            //数据，层级，当前li中的index，触发方式
            // console.log(item,level,index,trigger)
            if(item.disabled) {
                return false
            }

            // 选择时候移除默认选择项，高亮当前选项，添加class
            this.tempValue = []

            if(item.children) {
                // console.log(item)
                if(item.children.length>0) {
                    if(level == 1) {
                        Object.assign(this.active, this.$options.data().active)
                    }
                    // 加载children数据,level:1 一级，2：二级，3：三级
                    this.childData['data'+(level+1)] = ''
                    this.childData['data'+level] = item

                    // 选择既改变
                    if(this.changeOnSelect && trigger == 'click') {
                        let val = this.getParentVal(this.dataArr, item.value).reverse()
                        this.activeVal = val
                        this.valueCls
                        this.$emit('on-change',{'label':this.newValue,'value':val})
                    }
                }else{
                    //动态加载选项
                    this.loadData ? this.loadData(item,()=>{
                        this.loadDataCallback(item,level)
                    }) : ""
                }
            } else{
                // 当前项没有子级，只通过click赋值收起
                if(trigger == 'click') {
                    Object.assign(this.childData, this.$options.data().childData)
                    this.show = false
                    let value = this.getParentVal(this.dataArr, item.value).reverse()
                    this.activeVal = value
                    this.valueCls
                    // 选择既改变
                    if(this.changeOnSelect) {
                        this.$emit('on-change',{'label':this.newValue,'value':value})
                    }else{
                        this.$emit('on-change',{item,value})
                    }
                    this.$emit('on-open-change',this.show)
                }else{
                    this.childData['data'+level] = ''
                }
            }
            this.active['current'+(level)] = index
            this.$emit("input", this.activeVal)
            // console.log('加载子级',this.childData)
        },
        getParentVal(list, id) {
            // 递归符合value的所有父元素，返回value
            for (let i in list) {
                if (list[i].value == id) {
                    return [list[i].value]
                }
                if (list[i].children) {
                    let node = this.getParentVal(list[i].children, id);
                    if (node !== undefined) {
                        return node.concat(list[i].value)
                    }
                }
            }
        },
        getParentLabel(list, id) {
            // 递归符合value的所有父元素,返回label
            for (let i in list) {
                if (list[i].value == id) {
                    return [list[i].label]
                }
                if (list[i].children) {
                    let node = this.getParentLabel(list[i].children, id);
                    if (node !== undefined) {
                        return node.concat(list[i].label)
                    }
                }
            }
        },
        out(item,level) {
            // 鼠标移开，恢复操作时候的高亮为已选项高亮
            // this.active['current'+(level+1)] = ''
        },
        activeCls(item,level,index) {
            // 当前高亮添加class=active
            if(this.tempValue.indexOf(item.label)!=-1 || this.active['current'+level] === index) {
                return true
            }
        },
        clearValue() {
            // 初始化子级数据，如有已选的，展开
            Object.assign(this.active, this.$options.data().active)
            Object.assign(this.childData, this.$options.data().childData)
            this.newValue = ''
            this.activeVal = ''
            this.$emit('input','')
            // 选择既改变
            if(this.changeOnSelect) {
                this.$emit('on-change',{'label':'','value':''})
            }else{
                this.$emit('on-change',{'item':{'label':'','value':''},'value':''})
            }
        },
        loadDataCallback(item,level) {
            // console.log('%c动态加载回调loadDataCallback：','color:cyan',item,level)
            if(level == 1){
                // this.active.current2 = ''
                // this.active.current3 = ''
                // this.active.current4 = ''
                Object.assign(this.childData, this.$options.data().childData)
            }
            this.childData['data'+level] = item
        },
        filterKeyup() {
            this.show = true
        },
        filterKeyWord(k) {
            // console.log('搜索字段：',k)
            if(k) {
                this.filter.show = true;
                this.filter.list = '';

                this.newValue = ''
                // this.activeVal = ''
                // this.$emit('input','')

                let arr = [];
                this.dataArr.map( (d,i)=> {
                    arr.push(getChild(this.dataArr[i]))
                })
                let list = '';
                arr.map( (d,i)=> {
                    d.map( (r)=> {
                        let label = this.getParentLabel(this.dataArr, r.value).reverse()
                        let valArr = this.getParentVal(this.dataArr, r.value).reverse()
                        let val = '';
                        label.map((m,x)=>{
                            if(x < label.length-1) {
                                val = val + m + ' / '
                            }else{
                                val = val + m
                            }
                        })
                        if(val.indexOf(k) > -1) {
                            val = val.replace(k,'<span class="red">'+k+'</span>')
                            list += '<li onclick="selectItem(&quot;'+valArr+'&quot;)" class="'+(r.disabled?'disabled':'')+'">'+val+'</li>'
                        }
                    })
                })
                this.filter.list = list;

                // 执行找到最后一层
                function getChild(node) {
                  let arr = []
                  function search(node) {
                    if (node.children && node.children.length) {
                      for (let i = 0, len = node.children.length; i < len; i++) {
                        search(node.children[i])
                      }
                    } else {
                      arr.push(node)
                    }
                    return arr
                  }
                  search(node)
                  return arr
                }
            }else{
                this.filter.show = false;
            }

            // 搜索会改变内容高度，这里重新进行计算
            this.$nextTick(()=>{
                if(this.$refs.drop) {
                    const DOMRect1 = this.$refs.control.getBoundingClientRect(),
                          DOMRect2 = this.$refs.drop.getBoundingClientRect();
                    const _ch = document.documentElement.clientHeight, //浏览器可视化窗口的大小
                          _t1 = DOMRect1.top,
                          _h1 = DOMRect1.height,
                          _h2 = DOMRect2.height,
                          _st = window.pageYOffset //滚动高度
                    if(this.transfer) {
                        if (Number(_t1+_h1+_h2) > _ch) {
                            this.$refs.drop.style.top = (_t1-_h2+_st)+'px';
                        }
                    }else{
                        if (Number(_t1+_h1+_h2) > _ch) {
                            this.$refs.drop.style.marginTop = '-'+Number(_h1+_h2)+'px';
                        }
                    }
                }
            })
        },
        selectItem(value) {
            let arr = value.split(',')
            // console.log(arr)
            this.show = false
            this.filter.keyword = ''
            this.filter.placeholder = ''
            this.activeVal = arr
            this.valueCls
            this.$emit("input", this.activeVal)
            let label = this.newValue.split(' / ');
            this.$emit('on-change',{'item':{'label':label[label.length-1],'value':arr[arr.length-1]},'value':arr})
        }
    },
    computed:{
        valueCls() {
            let _this = this
            let val = '';
            if(this.activeVal.length > 0) {
                let len = this.activeVal.length - 1
                let label = this.getParentLabel(this.dataArr, this.activeVal[len])
                if(label){
                    label.reverse()
                    label.map((d,i)=>{
                        if(i < this.activeVal.length-1) {
                            val = val + d + ' / '
                        }else{
                            val = val + d
                        }
                    })
                }
                //赋值下级数据
                for(let i=0;i<this.activeVal.length;i++) {
                    this.dataArr.map((d)=>{
                        if(d.value == this.activeVal[i]) {
                            this.childData['data'+(i+1)] = d
                            if(d.children) {
                                d.children.map((r)=>{
                                    if(r.value == this.activeVal[i+1]) {
                                        this.childData['data'+(i+2)] = r
                                    }
                                })
                            }
                        }
                    })
                }
            }else{
                // 没有已选情况下，初始化子级数据
                Object.assign(this.childData, this.$options.data().childData)
            }
            this.newValue = val
            this.tempValue = val
        },
        classes() {
            return [
                `${prefixCls}-cascader`,
                {
                    'open': this.show,
                    [prefixCls + '-cascader-disabled']: this.disabled,
                    [prefixCls + '-cascader-' + this.size]: this.size
                }
            ]
        },
    },
    beforeDestroy () {
        document.removeEventListener('click', this._showHide)
    }
}
</script>